# coding: utf-8
import threading
from faker import Faker
from setting import app_cof
from com.files import f
from com.pickle_db import MyPickledb
from utils.service_redis import RedisClient
# 生成app_cof实例对象后导入才生效且不可删除ReadHandle包的导入
from src.utils.send_email import EmailSend
from src.utils.service_mysql import DBService
# noinspection PyUnresolvedReferences
from src.utils.file_yaml import ReadHandle
from src.utils.file_handle import GetFilePath
from src.utils.request_handle import RequestHandle
from src.utils.assert_handle import Assertion
from src.utils.base_utils import (SqlData, SqlResult)


# noinspection PyMethodMayBeStatic
class ApiCaseRevolution(RequestHandle, Assertion):
    """
    一、使用单例将当前类中的变量以及对象加载到内存中保存为唯一的内存ID, 后续考虑加锁
    二、提取所有公共对象, 将配置文件做到统一管理, 避免:
        1. 用例过多重复读取数据
        2. 数据获取错误时(例如mysql连接失败), 每有一个用例则加载一次mysql连接
        3. 在cases.__init__文件时重复增加、修改数据会导致目录混乱, 不便于数据管理
    三、可以通过globals_set在所有的用例中设置和获取全局/环境变量
    """
    __instance = {}
    lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if cls.__instance:
            return cls.__instance
        with cls.lock:
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
        return cls.__instance

    def __init__(self):
        # 全局变量、环境变量
        self.db = MyPickledb().my_db

    def __len__(self):
        return len(self.db.getall())

    def set(self, key, value):
        """设置全局变量"""
        self.db.set(key, value)

    def get(self, key):
        """获取全局变量的值"""
        return self.db.get(key)

    def has(self, key):
        """查询全局变量中是否包含key"""
        return self.db.exists(key)

    def _del(self, key, is_delete_all=False):
        """删除全局变量的key"""
        if is_delete_all:
            self.db.deldb()
        else:
            self.db.drem(key)

    # faker随机数据
    faker = Faker('zh_CN')
    # 文件处理
    file_handle = GetFilePath()
    # email
    email = EmailSend()

    # db: 根据环境允许链接数据库则创建db对象
    print("是否要使用数据库: ", app_cof.USE_MYSQL)
    if app_cof.USE_MYSQL:
        db = DBService()

    # redis: 根据环境允许链接数据库则创建redis_store对象
    print("是否使用redis: ", app_cof.USE_REDIS)
    if app_cof.USE_REDIS:
        redis_stroe: RedisClient = RedisClient({
            "host": app_cof.REDIS_HOST,
            "port": app_cof.REDIS_PORT,
            "db": app_cof.REDIS_NODE,
        })

    # 获取sql语句
    # 考虑当前用例的模块并不会有很多, 所以将sql语句写在一个文件内, 如果有需要可以根据模块分开
    sql_obj = SqlData()
    sql_data = sql_obj.get_sql_sentence(r"\sentence.yaml")

    # 获取sql处理结果
    sql_res = SqlResult()

    # 获取登录模块的用例数据
    path = f.yamlFile + r"\login.yaml"
    login_data = sql_obj.get_sql_sentence(r"\login.yaml")

    # 获取其他模块测试用例数据
    ...


apb: ApiCaseRevolution = ApiCaseRevolution()
